{% extends "base.html" %}

{% set active_page = "Info" %}

{% import 'macros.html' as macros %}
{% set count = [] %}

{% block head %}
<script src="{{ url_for("static", filename="node_modules/chart.js/dist/Chart.js") }}"></script>
<script type="text/javascript" src="{{ url_for('static', filename='js/fact_statistics.js') }}"></script>
{% endblock %}


{% block body %}
{% set query_url = "database/browse?query=" %}

<script type="text/javascript" src="{{ url_for("static", filename="js/update_url_variables.js") }}"></script>

<div class="row justify-content-center">
    <div class="col-lg-8 mt-4">
        <h3 class="mb-3">Firmware Statistics</h3>
    </div>
</div>

<div class="row justify-content-center" id="dropdown-div">
    <div class="col-lg-8 mb-4">
        <form>
            <div class="form-row">
                <div class="form-group col-lg-6" id="device-class-dropdown-div">
                    <label class="control-label" for="device_class_dropdown">Device Class:</label>
                    <select class="form-control" id="device_class_dropdown" name="device_class_dropdown"
                            onchange="window.location=update_url_variables(window.location.toString(), 'device_class', this.value)">
                        <option value=""></option>
                        {% for class in device_classes | sort %}
                            <option {% if class in current_class %}selected{% endif %} value="{{ class }}">{{ class }}</option>
                        {% endfor %}
                    </select>
                </div>

                <div class="form-group col-lg-6" id="vendor-dropdown-div">
                    <label class="control-label" for="vendor_dropdown">Vendor:</label>
                    <select class="form-control" id="vendor_dropdown" name="vendor_dropdown"
                            onchange="window.location=update_url_variables(window.location.toString(), 'vendor', this.value)">
                        <option value=""></option>
                        {% for vendor in vendors | sort %}
                            <option {% if vendor in current_vendor %}selected{% endif %} value="{{ vendor }}">{{ vendor }}</option>
                        {% endfor %}
                    </select>
                </div>
            </div>
        </form>
    </div>
</div>

<div class="row">


{# ------ General Stats ------ #}

     {% if stats["general_stats"] %}
        {% call macros.stats_panel("General") %}
            <table class="table table-responsive-md table-hover px-0 mb-0" style="width: 100%;">
                {{ macros.stats_table_row("firmware samples", stats["general_stats"]["number_of_firmwares"] | nice_number) }}
                {{ macros.stats_table_row("firmware total size", stats["general_stats"]["total_firmware_size"] | number_format) }}
                {{ macros.stats_table_row("firmware average size", stats["general_stats"]["average_firmware_size"] | number_format) }}
                {% if stats["general_stats"]["number_of_unique_files"] %}
                    {{ macros.stats_table_row("unique included files", stats["general_stats"]["number_of_unique_files"] | nice_number) }}
                    {{ macros.stats_table_row("unique included files total size", stats["general_stats"]["total_file_size"] | number_format) }}
                    {{ macros.stats_table_row("unique included files average size", stats["general_stats"]["average_file_size"] | number_format) }}
                {% endif %}
            </table>
        {% endcall %}
    {% endif %}


{# ------ Crypto Material Stats ------ #}

    {% if (stats["crypto_material_stats"]["crypto_material"] | length) > 0 %}
        {% call macros.stats_panel("Crypto Material", "lock") %}
            <table class="table table-responsive-md table-hover px-0 mb-0" style="width: 100%;">
            {% for item in (stats["crypto_material_stats"]["crypto_material"] | sort_chart_list_by_value) %}
                <tr>
                    <td style="text-align: left; padding:5px; cursor:pointer;"
                        {% set query = {"processed_analysis.crypto_material.summary": item[0]} %}
                        onclick="location.href='{{ query_url + query | json_dumps | urlencode }}'">
                        {{ item[0] }}
                    </td>
                    <td style="text-align: right; padding:5px;">{{ item[1] }}</td>
                </tr>
            {% endfor %}
            </table>
        {% endcall %}
    {% endif %}


{# ------ Known Vulnerability Stats ------ #}

    {% if (stats["known_vulnerabilities_stats"]["known_vulnerabilities"] | length) > 0 %}
        {% call macros.stats_panel("Known Vulnerabilities", "bolt") %}
            <table class="table table-responsive-md table-hover px-0 mb-0" style="width: 100%;">
            {% for item in (stats["known_vulnerabilities_stats"]["known_vulnerabilities"] | sort_chart_list_by_value) %}
                <tr>
                    <td style="text-align: left; padding:5px; cursor:pointer;"
                        {% set query = {"processed_analysis.known_vulnerabilities.summary": item[0]} %}
                        onclick="location.href='{{ query_url + query | json_dumps | urlencode }}'">
                        {{ item[0] }}
                    </td>
                    <td style="text-align: right; padding:5px;">{{ item[1] }}</td>
                </tr>
            {% endfor %}
            </table>
        {% endcall %}
    {% endif %}


{# ------ Unpacker Stats ------ #}

    {% if stats["unpacker_stats"]["overall_unpack_ratio"] %}
        {% call macros.stats_panel("Unpacker Stats", "file-archive") %}
            <table class="table table-responsive-md table-hover px-0 mb-0" style="width: 100%;">
                {{ macros.stats_table_row("Share of not-packed files", (stats["unpacker_stats"]["overall_unpack_ratio"] * 100) | nice_number, percent=True,
                   tooltip="Percentage of files that could not be further unpacked (outer vertices in the file tree), and are not considered packed") }}
                {{ macros.stats_table_row("Average packed entropy", stats["unpacker_stats"]["average_packed_entropy"] | nice_number, tooltip="Average byte entropy of files that are considered packed") }}
                {{ macros.stats_table_row("Average not-packed entropy", stats["unpacker_stats"]["average_unpacked_entropy"] | nice_number, tooltip="Average byte entropy of files that are not considered packed") }}
                {{ macros.stats_table_row("Ratio of data loss", (stats["unpacker_stats"]["overall_data_loss_ratio"] * 100) | nice_number, percent=True,
                   tooltip="Percentage of files that were unpacked (inner vertices in the file tree), where some data was probably lost (some files were not unpacked)") }}
            </table>
        {% endcall %}
    {% endif %}


{# ------ Charts ------ #}

{% set chart_list = [
    ["Vendors", "vendor", stats["firmware_meta_stats"], {"vendor": "PLACEHOLDER"}],
    ["Device Classes", "device_class", stats["firmware_meta_stats"], {"device_class": "PLACEHOLDER"}],
    ["Firmware Container", "firmware_container", stats["file_type_stats"],
        {"processed_analysis.file_type.mime": "PLACEHOLDER", "is_firmware": True}],
    ["File Types", "file_types", stats["file_type_stats"], {"processed_analysis.file_type.mime": "PLACEHOLDER"}],
    ["Unpacker Usage", "used_unpackers", stats["unpacker_stats"], {"processed_analysis.unpacker.plugin_used": "PLACEHOLDER"}],
    ["Unpacking Fail File Types", "packed_file_types", stats["unpacker_stats"],
        {"processed_analysis.unpacker.summary": "packed","processed_analysis.file_type.mime": "PLACEHOLDER"}],
    ["Data Lost File Types", "data_loss_file_types", stats["unpacker_stats"],
        {"processed_analysis.unpacker.summary": "data lost","processed_analysis.file_type.mime": "PLACEHOLDER"}],
    ["Architectures", "cpu_architecture", stats["architecture_stats"], {"processed_analysis.cpu_architecture.summary": {"$regex": "PLACEHOLDER"}}],
    ["Software Components", "software_components", stats["software_stats"], {"processed_analysis.software_components.PLACEHOLDER": {"$exists": "true"}}],
]%}

{% for title, key, data_set, query in chart_list %}
    {% if data_set %}
        {% if data_set[key] %}
            {% call macros.stats_panel(title) %}
                <canvas id="{{ key }}_canvas" width="80%" height="80%"></canvas>
                <script>
                    createPieChart(
                        canvasId="{{ key }}_canvas",
                        chartData={{ data_set[key] | sort_chart_list_by_value | data_to_chart_limited | safe }},
                        link="{{ query_url + query | json_dumps | urlencode }}"
                    );
                </script>
            {% endcall %}
        {% endif %}
    {% endif %}
{% endfor %}


{# ------ Exploit Mitigation Stats ------ #}

{% if stats["exploit_mitigations_stats"] %}
    {% if stats["exploit_mitigations_stats"]["exploit_mitigations"] %}
        {% call macros.stats_panel("Exploit Mitigations") %}
            <canvas id="exploit_mitigations_canvas" width="100%" height="{{ stats['exploit_mitigations_stats']['exploit_mitigations'] | get_canvas_height }}"></canvas>
            <script>
                createHorizontalBarChart(
                    canvasId="exploit_mitigations_canvas",
                    chartData={{ stats['exploit_mitigations_stats']['exploit_mitigations'] | data_to_chart_with_value_percentage_pairs(limit=13) | safe }},
                    link="{{ query_url + {'processed_analysis.exploit_mitigations.summary': {'$regex': 'PLACEHOLDER'}} | json_dumps | urlencode }}",
                    expl_mit_flag=true
                );
            </script>
        {% endcall %}
    {% endif %}
{% endif %}


{# ------ ELF Executable Stats ------ #}

{% if stats["elf_executable_stats"] %}
    {% if stats["elf_executable_stats"]["executable_stats"] %}
        {% call macros.stats_panel("ELF Executables") %}
            <canvas id="elf_executable_canvas" width="100%" height="{{ stats['elf_executable_stats']['executable_stats'] | get_canvas_height }}"></canvas>
            <script>
                createHorizontalBarChart(
                    canvasId="elf_executable_canvas",
                    chartData={{ stats["elf_executable_stats"]["executable_stats"] | data_to_chart_with_value_percentage_pairs(limit=11) | safe }},
                    link="{{ query_url + {'processed_analysis.file_type.full': {'$regex': 'PLACEHOLDER'}} | json_dumps | urlencode }}",
                    isPercentage=true, linksInData=true
                );
            </script>
        {% endcall %}
    {% endif %}
{% endif %}


{# ------ IP Stats ------ #}

    {% set ips_v4_num = stats["ip_and_uri_stats"]["ips_v4"] | length %}
    {% if ips_v4_num > 0 %}
        {% call macros.stats_panel("IPv4 Addresses (Top {}/{})".format([10, ips_v4_num] | min, ips_v4_num), "globe") %}
            <table class="table table-responsive-md table-hover px-0 mb-0" style="width: 100%;">
            {% for ip, count in (stats["ip_and_uri_stats"]["ips_v4"] | sort_chart_list_by_value)[:10] %}
                {% set query = {"processed_analysis.ip_and_uri_finder.ips_v4": {"$contains": [{"address": ip}]}} %}
                {{ macros.stats_table_row(ip, count, link=query_url + query | json_dumps | urlencode) }}
            {% endfor %}
            </table>
        {% endcall %}
    {% endif %}

    {% set ips_v6_num = stats["ip_and_uri_stats"]["ips_v6"] | length %}
    {% if ips_v6_num > 0 %}
        {% call macros.stats_panel("IPv6 Addresses (Top {}/{})".format([10, ips_v6_num] | min, ips_v6_num), "globe") %}
            <table class="table table-responsive-md table-hover px-0 mb-0" style="width: 100%;">
            {% for ip, count in (stats["ip_and_uri_stats"]["ips_v6"] | sort_chart_list_by_value)[:10] %}
                {% set query = {"processed_analysis.ip_and_uri_finder.ips_v6": {"$contains": [{"address": ip}]}} %}
                {{ macros.stats_table_row(ip, count, link=query_url + query | json_dumps | urlencode) }}
            {% endfor %}
            </table>
        {% endcall %}
    {% endif %}

    {% set uri_num = stats["ip_and_uri_stats"]["uris"] | length %}
    {% if uri_num > 0 %}
        {% call macros.stats_panel("URIs (Top {}/{})".format([10, uri_num] | min, uri_num), "globe") %}
            <table class="table table-responsive-md table-hover px-0 mb-0" style="width: 100%;">
            {% for uri, count in (stats["ip_and_uri_stats"]["uris"] | sort_chart_list_by_value)[:10] %}
                {% set query = {"processed_analysis.ip_and_uri_finder.uris": {"$contains": uri}} %}
                {{ macros.stats_table_row(uri, count, link=query_url + query | json_dumps | urlencode) }}
            {% endfor %}
            </table>
        {% endcall %}
    {% endif %}

</div>


{# ------ Release Date Histogram ------ #}

{% if (stats["release_date_stats"]["date_histogram_data"] | length) > 0 %}
<div class="row justify-content-center mb-2">
    <div class="col-lg-8 card bg-light rounded border-0">
        <div class="card-body">
            <h5 class="card-title mt-2"><i class="far fa-calendar-alt"></i> Release Date Stats</h5>
            <div class="card-text">
                <canvas id="release_date_canvas"></canvas>
                <script>
                    const DateBarChart = createHistogram(
                        "release_date_canvas",
                        {{ stats["release_date_stats"]["date_histogram_data"] | data_to_chart | safe }}
                    );
                    document.getElementById("release_date_canvas").onclick = function(evt){
                        const points = DateBarChart.getElementsAtEvent(evt);
                        const date = DateBarChart.data.labels[points[0]._index];
                        if (points[0] !== undefined)
                            window.location = "database/browse?date=" + date;
                    };
                </script>
            </div>
        </div>
    </div>
</div>
{% endif %}

{# ------ Footer ------ #}

{% if stats["general_stats"] %}

<div class="row">
    <div class="col-lg-12" style="text-align:center;">These statistics were generated at: <b>{{ stats["general_stats"]["creation_time"] | nice_unix_time }}</b> in <b>{{ stats["general_stats"]["benchmark"] | nice_time }}</b></div>
</div>

{% else %}

<div class="alert alert-danger">
  <strong>No statistics available!</strong><br /> Run the update_statistic program.
</div>

{% endif %}


{% endblock %}
